/*-------------------------------------------------------------------------
 *
 * jsonapi.c
 *		JSON 解析器和词法分析器接口
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * IDENTIFICATION
 *	  src/common/jsonapi.c
 *
 *-------------------------------------------------------------------------
 */
#ifndef FRONTEND
#include "postgres.h"
#else
#include "postgres_fe.h"
#endif

#include "common/jsonapi.h"
#include "mb/pg_wchar.h"

#ifndef FRONTEND
#include "miscadmin.h"
#endif

/*
 * 解析器的上下文由递归下降机制维护，但为了更好的诊断，明确传递给错误报告例程。
 */
typedef enum					/* JSON解析器的上下文 */
{
	JSON_PARSE_VALUE,			/* 期待一个值 */
	JSON_PARSE_STRING,			/* 期待一个字符串（用于字段名称） */
	JSON_PARSE_ARRAY_START,		/* 看到'[', 期待值或']' */
	JSON_PARSE_ARRAY_NEXT,		/* 看到数组元素，期待','或']' */
	JSON_PARSE_OBJECT_START,	/* 看到'{', 期待标签或'}' */
	JSON_PARSE_OBJECT_LABEL,	/* 看到对象标签，期待':' */
	JSON_PARSE_OBJECT_NEXT,		/* 看到对象值，期待','或'}' */
	JSON_PARSE_OBJECT_COMMA,	/* 看到对象','，期待下一个标签 */
	JSON_PARSE_END				/* 看到文档末尾，什么也不期待 */
} JsonParseContext;

static inline JsonParseErrorType fc_json_lex_string(JsonLexContext *fc_lex);
static inline JsonParseErrorType fc_json_lex_number(JsonLexContext *fc_lex, char *fc_s,
												 bool *fc_num_err, int *fc_total_len);
static inline JsonParseErrorType fc_parse_scalar(JsonLexContext *fc_lex, JsonSemAction *fc_sem);
static JsonParseErrorType fc_parse_object_field(JsonLexContext *fc_lex, JsonSemAction *fc_sem);
static JsonParseErrorType fc_parse_object(JsonLexContext *fc_lex, JsonSemAction *fc_sem);
static JsonParseErrorType fc_parse_array_element(JsonLexContext *fc_lex, JsonSemAction *fc_sem);
static JsonParseErrorType fc_parse_array(JsonLexContext *fc_lex, JsonSemAction *fc_sem);
static JsonParseErrorType fc_report_parse_error(JsonParseContext fc_ctx, JsonLexContext *fc_lex);

/* 用于纯验证的空操作对象 */
JsonSemAction nullSemAction =
{
	NULL, NULL, NULL, NULL, NULL,
	NULL, NULL, NULL, NULL, NULL
};

/* 递归下降解析器支持例程 */

/*
 * lex_peek
 *
 * 当前的前瞻标记是什么？
*/
static inline JsonTokenType
fc_lex_peek(JsonLexContext *fc_lex)
{
	return fc_lex->token_type;
}

/*
 * lex_expect
 *
 * 如果当前的前瞻标记与参数标记匹配，则将词法分析器移动到下一个标记。
 * 否则，报告一个错误。
 */
static inline JsonParseErrorType fc_lex_expect(JsonParseContext fc_ctx, JsonLexContext *fc_lex, JsonTokenType fc_token)
{
	if (fc_lex_peek(fc_lex) == fc_token)
		return json_lex(fc_lex);
	else
		return fc_report_parse_error(fc_ctx, fc_lex);
}

/* 要视为字母数字标记一部分的字符 */
#define JSON_ALPHANUMERIC_CHAR(c)  \
	(((c) >= 'a' && (c) <= 'z') || \
	 ((c) >= 'A' && (c) <= 'Z') || \
	 ((c) >= '0' && (c) <= '9') || \
	 (c) == '_' || \
	 IS_HIGHBIT_SET(c))

/*
 * 实用函数，用于检查字符串是否为有效的JSON数字。
 *
 * str的长度为len，并且不需要以null结尾。
 */
bool IsValidJsonNumber(const char *fc_str, int fc_len)
{
	bool		fc_numeric_error;
	int			fc_total_len;
	JsonLexContext fc_dummy_lex;

	if (fc_len <= 0)
		return false;

	/*
	 * json_lex_number期望一个前导'-'已经被解析。
	 *
	 * 强制去掉str的常量性是丑陋的，但没有更简单的替代方案。
	 */
	if (*fc_str == '-')
	{
		fc_dummy_lex.input = unconstify(char *, fc_str) + 1;
		fc_dummy_lex.input_length = fc_len - 1;
	}
	else
	{
		fc_dummy_lex.input = unconstify(char *, fc_str);
		fc_dummy_lex.input_length = fc_len;
	}

	fc_json_lex_number(&fc_dummy_lex, fc_dummy_lex.input, &fc_numeric_error, &fc_total_len);

	return (!fc_numeric_error) && (fc_total_len == fc_dummy_lex.input_length);
}

/*
 * makeJsonLexContextCstringLen
 *
 * 词法构造函数，无论是否有StringInfo对象用于去转义的词素。
 *
 * 没有时更好，因为这使处理更快，所以只有在确实需要时才创建一个。
 */
JsonLexContext *
makeJsonLexContextCstringLen(char *fc_json, int fc_len, int fc_encoding, bool fc_need_escapes)
{
	JsonLexContext *fc_lex = palloc0(sizeof(JsonLexContext));

	fc_lex->input = fc_lex->token_terminator = fc_lex->line_start = fc_json;
	fc_lex->line_number = 1;
	fc_lex->input_length = fc_len;
	fc_lex->input_encoding = fc_encoding;
	if (fc_need_escapes)
		fc_lex->strval = makeStringInfo();
	return fc_lex;
}

/*
 * pg_parse_json
 *
 * JSON解析器的公开入口点。
 *
 * lex是一个词法上下文，通过调用makeJsonLexContext()设置好，用于处理JSON。
 * sem是一个结构，包含在解析期间在适当位置调用的语义操作例程的函数指针，
 * 以及一个指向将传递给这些例程的状态对象的指针。
 */
JsonParseErrorType pg_parse_json(JsonLexContext *fc_lex, JsonSemAction *fc_sem)
{
	JsonTokenType fc_tok;
	JsonParseErrorType fc_result;

	/* 获取初始标记 */
	fc_result = json_lex(fc_lex);
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	fc_tok = fc_lex_peek(fc_lex);

	/* 通过递归下降进行解析 */
	switch (fc_tok)
	{
		case JSON_TOKEN_OBJECT_START:
			fc_result = fc_parse_object(fc_lex, fc_sem);
			break;
		case JSON_TOKEN_ARRAY_START:
			fc_result = fc_parse_array(fc_lex, fc_sem);
			break;
		default:
			fc_result = fc_parse_scalar(fc_lex, fc_sem);	/* JSON可以是一个裸标量 */
	}

	if (fc_result == JSON_SUCCESS)
		fc_result = fc_lex_expect(JSON_PARSE_END, fc_lex, JSON_TOKEN_END);

	return fc_result;
}

/*
 * json_count_array_elements
 *
 * 返回在数组标记开始时的词法上下文中，直到同一嵌套级别的数组标记结束时的数组元素数量。
 *
 * 设计为从array_start例程调用。
 */
JsonParseErrorType json_count_array_elements(JsonLexContext *fc_lex, int *fc_elements)
{
	JsonLexContext fc_copylex;
	int			fc_count;
	JsonParseErrorType fc_result;

	/*
	 * 进行这样的浅拷贝是安全的，因为词法例程不会在输入上乱写。
	 * 它们确实会在其他指针等上乱写，因此使用副本进行此操作使其安全。
	 */
	memcpy(&fc_copylex, fc_lex, sizeof(JsonLexContext));
	fc_copylex.strval = NULL;		/* 在这里不关注值 */
	fc_copylex.lex_level++;

	fc_count = 0;
	fc_result = fc_lex_expect(JSON_PARSE_ARRAY_START, &fc_copylex,
						JSON_TOKEN_ARRAY_START);
	if (fc_result != JSON_SUCCESS)
		return fc_result;
	if (fc_lex_peek(&fc_copylex) != JSON_TOKEN_ARRAY_END)
	{
		while (1)
		{
			fc_count++;
			fc_result = fc_parse_array_element(&fc_copylex, &nullSemAction);
			if (fc_result != JSON_SUCCESS)
				return fc_result;
			if (fc_copylex.token_type != JSON_TOKEN_COMMA)
				break;
			fc_result = json_lex(&fc_copylex);
			if (fc_result != JSON_SUCCESS)
				return fc_result;
		}
	}
	fc_result = fc_lex_expect(JSON_PARSE_ARRAY_NEXT, &fc_copylex,
						JSON_TOKEN_ARRAY_END);
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	*fc_elements = fc_count;
	return JSON_SUCCESS;
}

/*
 * 递归下降解析例程。每个结构性元素都有一个JSON文档：
 *	  - 标量（字符串、数字、true、false、null）
 *	  - 数组（[ ]）
 *	  - 数组元素
 *	  - 对象（{ }）
 *	  - 对象字段
 */
static inline JsonParseErrorType fc_parse_scalar(JsonLexContext *fc_lex, JsonSemAction *fc_sem)
{
	char	   *fc_val = NULL;
	json_scalar_action fc_sfunc = fc_sem->scalar;
	JsonTokenType fc_tok = fc_lex_peek(fc_lex);
	JsonParseErrorType fc_result;

	/* 标量必须是字符串、数字、true、false或null */
	if (fc_tok != JSON_TOKEN_STRING && fc_tok != JSON_TOKEN_NUMBER &&
		fc_tok != JSON_TOKEN_TRUE && fc_tok != JSON_TOKEN_FALSE &&
		fc_tok != JSON_TOKEN_NULL)
		return fc_report_parse_error(JSON_PARSE_VALUE, fc_lex);

	/* 如果没有语义函数，仅消耗标记 */
	if (fc_sfunc == NULL)
		return json_lex(fc_lex);

	/* 提取去转义的字符串值或原始词素 */
	if (fc_lex_peek(fc_lex) == JSON_TOKEN_STRING)
	{
		if (fc_lex->strval != NULL)
			fc_val = pstrdup(fc_lex->strval->data);
	}
	else
	{
		int			fc_len = (fc_lex->token_terminator - fc_lex->token_start);

		fc_val = palloc(fc_len + 1);
		memcpy(fc_val, fc_lex->token_start, fc_len);
		fc_val[fc_len] = '\0';
	}

	/* 消耗标记 */
	fc_result = json_lex(fc_lex);
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	/* 调用回调 */
	(*fc_sfunc) (fc_sem->semstate, fc_val, fc_tok);

	return JSON_SUCCESS;
}

static JsonParseErrorType fc_parse_object_field(JsonLexContext *fc_lex, JsonSemAction *fc_sem)
{
	/*
	 * 对象字段为 "fieldname" : value，其中 value 可以是一个标量、对象或数组。
	 * 注意：在面向用户的文档和错误消息中，我们通常称字段名称为 "key"。
	 */

	char	   *fc_fname = NULL;	/* 保持编译器安静 */
	json_ofield_action fc_ostart = fc_sem->object_field_start;
	json_ofield_action fc_oend = fc_sem->object_field_end;
	bool		fc_isnull;
	JsonTokenType fc_tok;
	JsonParseErrorType fc_result;

	if (fc_lex_peek(fc_lex) != JSON_TOKEN_STRING)
		return fc_report_parse_error(JSON_PARSE_STRING, fc_lex);
	if ((fc_ostart != NULL || fc_oend != NULL) && fc_lex->strval != NULL)
		fc_fname = pstrdup(fc_lex->strval->data);
	fc_result = json_lex(fc_lex);
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	fc_result = fc_lex_expect(JSON_PARSE_OBJECT_LABEL, fc_lex, JSON_TOKEN_COLON);
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	fc_tok = fc_lex_peek(fc_lex);
	fc_isnull = fc_tok == JSON_TOKEN_NULL;

	if (fc_ostart != NULL)
		(*fc_ostart) (fc_sem->semstate, fc_fname, fc_isnull);

	switch (fc_tok)
	{
		case JSON_TOKEN_OBJECT_START:
			fc_result = fc_parse_object(fc_lex, fc_sem);
			break;
		case JSON_TOKEN_ARRAY_START:
			fc_result = fc_parse_array(fc_lex, fc_sem);
			break;
		default:
			fc_result = fc_parse_scalar(fc_lex, fc_sem);
	}
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	if (fc_oend != NULL)
		(*fc_oend) (fc_sem->semstate, fc_fname, fc_isnull);
	return JSON_SUCCESS;
}

static JsonParseErrorType fc_parse_object(JsonLexContext *fc_lex, JsonSemAction *fc_sem)
{
	/*
	 * 对象是一个可能为空的对象字段序列，字段之间用逗号分隔，并且被花括号包围。
	 */
	json_struct_action fc_ostart = fc_sem->object_start;
	json_struct_action fc_oend = fc_sem->object_end;
	JsonTokenType fc_tok;
	JsonParseErrorType fc_result;

#ifndef FRONTEND
	check_stack_depth();
#endif

	if (fc_ostart != NULL)
		(*fc_ostart) (fc_sem->semstate);

	/*
	 * 对象内部的数据位于比对象本身更高的嵌套级别。
	 * 注意，我们在调用对象开始的语义例程后递增这个级别，并在调用对象结束的例程前恢复它。
	 */
	fc_lex->lex_level++;

	Assert(fc_lex_peek(fc_lex) == JSON_TOKEN_OBJECT_START);
	fc_result = json_lex(fc_lex);
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	fc_tok = fc_lex_peek(fc_lex);
	switch (fc_tok)
	{
		case JSON_TOKEN_STRING:
			fc_result = fc_parse_object_field(fc_lex, fc_sem);
			while (fc_result == JSON_SUCCESS && fc_lex_peek(fc_lex) == JSON_TOKEN_COMMA)
			{
				fc_result = json_lex(fc_lex);
				if (fc_result != JSON_SUCCESS)
					break;
				fc_result = fc_parse_object_field(fc_lex, fc_sem);
			}
			break;
		case JSON_TOKEN_OBJECT_END:
			break;
		default:
			/* 对于对象内部无效初始标记的情况 */
			fc_result = fc_report_parse_error(JSON_PARSE_OBJECT_START, fc_lex);
	}
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	fc_result = fc_lex_expect(JSON_PARSE_OBJECT_NEXT, fc_lex, JSON_TOKEN_OBJECT_END);
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	fc_lex->lex_level--;

	if (fc_oend != NULL)
		(*fc_oend) (fc_sem->semstate);

	return JSON_SUCCESS;
}

static JsonParseErrorType fc_parse_array_element(JsonLexContext *fc_lex, JsonSemAction *fc_sem)
{
	json_aelem_action fc_astart = fc_sem->array_element_start;
	json_aelem_action fc_aend = fc_sem->array_element_end;
	JsonTokenType fc_tok = fc_lex_peek(fc_lex);
	JsonParseErrorType fc_result;

	bool		fc_isnull;

	fc_isnull = fc_tok == JSON_TOKEN_NULL;

	if (fc_astart != NULL)
		(*fc_astart) (fc_sem->semstate, fc_isnull);

	/* 数组元素是任何对象、数组或标量 */
	switch (fc_tok)
	{
		case JSON_TOKEN_OBJECT_START:
			fc_result = fc_parse_object(fc_lex, fc_sem);
			break;
		case JSON_TOKEN_ARRAY_START:
			fc_result = fc_parse_array(fc_lex, fc_sem);
			break;
		default:
			fc_result = fc_parse_scalar(fc_lex, fc_sem);
	}

	if (fc_result != JSON_SUCCESS)
		return fc_result;

	if (fc_aend != NULL)
		(*fc_aend) (fc_sem->semstate, fc_isnull);

	return JSON_SUCCESS;
}

static JsonParseErrorType fc_parse_array(JsonLexContext *fc_lex, JsonSemAction *fc_sem)
{
	/*
	 * 数组是一个可能为空的数组元素序列，元素之间用逗号分隔，并且被方括号包围。
	 */
	json_struct_action fc_astart = fc_sem->array_start;
	json_struct_action fc_aend = fc_sem->array_end;
	JsonParseErrorType fc_result;

#ifndef FRONTEND
	check_stack_depth();
#endif

	if (fc_astart != NULL)
		(*fc_astart) (fc_sem->semstate);

	/*
	 * 数组内部的数据位于比数组本身更高的嵌套级别。
	 * 注意，我们在调用数组开始的语义例程后递增这个级别，并在调用数组结束的例程前恢复它。
	 */
	fc_lex->lex_level++;

	fc_result = fc_lex_expect(JSON_PARSE_ARRAY_START, fc_lex, JSON_TOKEN_ARRAY_START);
	if (fc_result == JSON_SUCCESS && fc_lex_peek(fc_lex) != JSON_TOKEN_ARRAY_END)
	{
		fc_result = fc_parse_array_element(fc_lex, fc_sem);

		while (fc_result == JSON_SUCCESS && fc_lex_peek(fc_lex) == JSON_TOKEN_COMMA)
		{
			fc_result = json_lex(fc_lex);
			if (fc_result != JSON_SUCCESS)
				break;
			fc_result = fc_parse_array_element(fc_lex, fc_sem);
		}
	}
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	fc_result = fc_lex_expect(JSON_PARSE_ARRAY_NEXT, fc_lex, JSON_TOKEN_ARRAY_END);
	if (fc_result != JSON_SUCCESS)
		return fc_result;

	fc_lex->lex_level--;

	if (fc_aend != NULL)
		(*fc_aend) (fc_sem->semstate);

	return JSON_SUCCESS;
}

/*
 * 从输入流中分析一个标记。
 */
JsonParseErrorType json_lex(JsonLexContext *fc_lex)
{
	char	   *fc_s;
	int			fc_len;
	JsonParseErrorType fc_result;

	/* 跳过前导空白。 */
	fc_s = fc_lex->token_terminator;
	fc_len = fc_s - fc_lex->input;
	while (fc_len < fc_lex->input_length &&
		   (*fc_s == ' ' || *fc_s == '\t' || *fc_s == '\n' || *fc_s == '\r'))
	{
		if (*fc_s++ == '\n')
		{
			++fc_lex->line_number;
			fc_lex->line_start = fc_s;
		}
		fc_len++;
	}
	fc_lex->token_start = fc_s;

	/* 确定标记类型。 */
	if (fc_len >= fc_lex->input_length)
	{
		fc_lex->token_start = NULL;
		fc_lex->prev_token_terminator = fc_lex->token_terminator;
		fc_lex->token_terminator = fc_s;
		fc_lex->token_type = JSON_TOKEN_END;
	}
	else
	{
		switch (*fc_s)
		{
				/* 单字符标记，某种标点符号。 */
			case '{':
				fc_lex->prev_token_terminator = fc_lex->token_terminator;
				fc_lex->token_terminator = fc_s + 1;
				fc_lex->token_type = JSON_TOKEN_OBJECT_START;
				break;
			case '}':
				fc_lex->prev_token_terminator = fc_lex->token_terminator;
				fc_lex->token_terminator = fc_s + 1;
				fc_lex->token_type = JSON_TOKEN_OBJECT_END;
				break;
			case '[':
				fc_lex->prev_token_terminator = fc_lex->token_terminator;
				fc_lex->token_terminator = fc_s + 1;
				fc_lex->token_type = JSON_TOKEN_ARRAY_START;
				break;
			case ']':
				fc_lex->prev_token_terminator = fc_lex->token_terminator;
				fc_lex->token_terminator = fc_s + 1;
				fc_lex->token_type = JSON_TOKEN_ARRAY_END;
				break;
			case ',':
				fc_lex->prev_token_terminator = fc_lex->token_terminator;
				fc_lex->token_terminator = fc_s + 1;
				fc_lex->token_type = JSON_TOKEN_COMMA;
				break;
			case ':':
				fc_lex->prev_token_terminator = fc_lex->token_terminator;
				fc_lex->token_terminator = fc_s + 1;
				fc_lex->token_type = JSON_TOKEN_COLON;
				break;
			case '"':
				/* 字符串 */
				fc_result = fc_json_lex_string(fc_lex);
				if (fc_result != JSON_SUCCESS)
					return fc_result;
				fc_lex->token_type = JSON_TOKEN_STRING;
				break;
			case '-':
				/* 负数。 */
				fc_result = fc_json_lex_number(fc_lex, fc_s + 1, NULL, NULL);
				if (fc_result != JSON_SUCCESS)
					return fc_result;
				fc_lex->token_type = JSON_TOKEN_NUMBER;
				break;
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				/* 正数。 */
				fc_result = fc_json_lex_number(fc_lex, fc_s, NULL, NULL);
				if (fc_result != JSON_SUCCESS)
					return fc_result;
				fc_lex->token_type = JSON_TOKEN_NUMBER;
				break;
			default:
				{
					char	   *fc_p;

					/*
					 * 我们没有处理一个字符串、数字、合法的标点符号或字符串结束。
					 * 这里唯一合法的标记可能是 true、false 和 null，
					 * 但为了错误报告的目的，我们会扫描直到看到一个
					 * 非字母数字字符。这样，我们可以将整个单词报告
					 * 为一个意外的标记，而不是仅仅某个不直观的前缀。
					 */
					for (fc_p = fc_s; fc_p - fc_s < fc_lex->input_length - fc_len && JSON_ALPHANUMERIC_CHAR(*fc_p); fc_p++)
						 /* 跳过 */ ;

					/*
					 * 我们得到了某种意外的标点符号或其他意外字符，
					 * 所以只对那个字符提出投诉。
					 */
					if (fc_p == fc_s)
					{
						fc_lex->prev_token_terminator = fc_lex->token_terminator;
						fc_lex->token_terminator = fc_s + 1;
						return JSON_INVALID_TOKEN;
					}

					/*
					 * 我们这里有一个真正的字母数字标记。如果它恰好是
					 * true、false 或 null，一切都很好。如果不是，则出错。
					 */
					fc_lex->prev_token_terminator = fc_lex->token_terminator;
					fc_lex->token_terminator = fc_p;
					if (fc_p - fc_s == 4)
					{
						if (memcmp(fc_s, "true", 4) == 0)
							fc_lex->token_type = JSON_TOKEN_TRUE;
						else if (memcmp(fc_s, "null", 4) == 0)
							fc_lex->token_type = JSON_TOKEN_NULL;
						else
							return JSON_INVALID_TOKEN;
					}
					else if (fc_p - fc_s == 5 && memcmp(fc_s, "false", 5) == 0)
						fc_lex->token_type = JSON_TOKEN_FALSE;
					else
						return JSON_INVALID_TOKEN;
				}
		}						/* switch 结束 */
	}

	return JSON_SUCCESS;
}

/*
 * 输入流中的下一个标记被知晓为字符串；进行词法分析。
 *
 * 如果 lex->strval 不是 NULL，使用解码字符串填充它。
 * 将 lex->token_terminator 设置为解码输入的末尾，并在
 * 成功情况下将其先前的值转移到 lex->prev_token_terminator。
 * 返回 JSON_SUCCESS 或错误代码。
 *
 * 注意：确保所有错误退出将 lex->token_terminator
 * 向前推进到我们检测到错误的字符之后的点。
 */
static inline JsonParseErrorType fc_json_lex_string(JsonLexContext *fc_lex)
{
	char	   *fc_s;
	char	   *const fc_end = fc_lex->input + fc_lex->input_length;
	int			fc_len;
	int			fc_hi_surrogate = -1;

	/* 错误退出的便利宏 */
#define FAIL_AT_CHAR_START(code) \
	do { \
		fc_lex->token_terminator = fc_s; \
		return code; \
	} while (0)
#define FAIL_AT_CHAR_END(code) \
	do { \
		char	   *fc_term = fc_s + pg_encoding_mblen(fc_lex->input_encoding, fc_s); \
		fc_lex->token_terminator = (fc_term <= fc_end) ? fc_term : fc_end; \
		return code; \
	} while (0)

	if (fc_lex->strval != NULL)
		resetStringInfo(fc_lex->strval);

	Assert(fc_lex->input_length > 0);
	fc_s = fc_lex->token_start;
	fc_len = fc_lex->token_start - fc_lex->input;
	for (;;)
	{
		fc_s++;
		fc_len++;
		/* 字符串的过早结束。 */
		if (fc_len >= fc_lex->input_length)
			FAIL_AT_CHAR_START(JSON_INVALID_TOKEN);
		else if (*fc_s == '"')
			break;
		else if ((unsigned char) *fc_s < 32)
		{
			/* 根据 RFC4627，这些字符必须被转义。 */
			/* 由于 *s 不是可打印的，排除它的上下文字符串 */
			FAIL_AT_CHAR_START(JSON_ESCAPING_REQUIRED);
		}
		else if (*fc_s == '\\')
		{
			/* 好的，我们有一个转义字符。 */
			fc_s++;
			fc_len++;
			if (fc_len >= fc_lex->input_length)
				FAIL_AT_CHAR_START(JSON_INVALID_TOKEN);
			else if (*fc_s == 'u')
			{
				int			fc_i;
				int			fc_ch = 0;

				for (fc_i = 1; fc_i <= 4; fc_i++)
				{
					fc_s++;
					fc_len++;
					if (fc_len >= fc_lex->input_length)
						FAIL_AT_CHAR_START(JSON_INVALID_TOKEN);
					else if (*fc_s >= '0' && *fc_s <= '9')
						fc_ch = (fc_ch * 16) + (*fc_s - '0');
					else if (*fc_s >= 'a' && *fc_s <= 'f')
						fc_ch = (fc_ch * 16) + (*fc_s - 'a') + 10;
					else if (*fc_s >= 'A' && *fc_s <= 'F')
						fc_ch = (fc_ch * 16) + (*fc_s - 'A') + 10;
					else
						FAIL_AT_CHAR_END(JSON_UNICODE_ESCAPE_FORMAT);
				}
				if (fc_lex->strval != NULL)
				{
					/*
					 * 组合代理对。
					 */
					if (is_utf16_surrogate_first(fc_ch))
					{
						if (fc_hi_surrogate != -1)
							FAIL_AT_CHAR_END(JSON_UNICODE_HIGH_SURROGATE);
						fc_hi_surrogate = fc_ch;
						continue;
					}
					else if (is_utf16_surrogate_second(fc_ch))
					{
						if (fc_hi_surrogate == -1)
							FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);
						fc_ch = surrogate_pair_to_codepoint(fc_hi_surrogate, fc_ch);
						fc_hi_surrogate = -1;
					}

					if (fc_hi_surrogate != -1)
						FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);

					/*
					 * 拒绝无效情况。这里不能有大于
					 * 0xFFFF 的值（因为我们之前只接受了4个十六进制数字），
					 * 所以没必要测试越界字符。
					 */
					if (fc_ch == 0)
					{
						/* 我们不能允许这样，因为我们的 TEXT 类型不这样做 */
						FAIL_AT_CHAR_END(JSON_UNICODE_CODE_POINT_ZERO);
					}

					/*
					 * 将表示的字符添加到 lex->strval 中。在
					 * 后端，我们可以让 pg_unicode_to_server() 处理任何
					 * 所需的字符集转换；在前端，我们只能处理简单的转换。
					 *
					 * 注意：pg_unicode_to_server() 会因转换失败而抛出错误，
					 * 而不是返回失败指示。这似乎没问题。
					 */
#ifndef FRONTEND
					{
						char		fc_cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1];

						pg_unicode_to_server(fc_ch, (unsigned char *) fc_cbuf);
						appendStringInfoString(fc_lex->strval, fc_cbuf);
					}
#else
					if (fc_lex->input_encoding == PG_UTF8)
					{
						/* 好的，我们可以轻松地将代码点映射到 UTF8 */
						char		fc_utf8str[5];
						int			fc_utf8len;

						unicode_to_utf8(fc_ch, (unsigned char *) fc_utf8str);
						fc_utf8len = pg_utf_mblen((unsigned char *) fc_utf8str);
						appendBinaryStringInfo(fc_lex->strval, fc_utf8str, fc_utf8len);
					}
					else if (fc_ch <= 0x007f)
					{
						/* ASCII 范围在所有编码中都是一样的 */
						appendStringInfoChar(fc_lex->strval, (char) fc_ch);
					}
					else
						FAIL_AT_CHAR_END(JSON_UNICODE_HIGH_ESCAPE);
#endif							/* FRONTEND */
				}
			}
			else if (fc_lex->strval != NULL)
			{
				if (fc_hi_surrogate != -1)
					FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);

				switch (*fc_s)
				{
					case '"':
					case '\\':
					case '/':
						appendStringInfoChar(fc_lex->strval, *fc_s);
						break;
					case 'b':
						appendStringInfoChar(fc_lex->strval, '\b');
						break;
					case 'f':
						appendStringInfoChar(fc_lex->strval, '\f');
						break;
					case 'n':
						appendStringInfoChar(fc_lex->strval, '\n');
						break;
					case 'r':
						appendStringInfoChar(fc_lex->strval, '\r');
						break;
					case 't':
						appendStringInfoChar(fc_lex->strval, '\t');
						break;
					default:

						/*
						 * 不是有效的字符串转义，因此报告错误。我们
						 * 调整 token_start，以便只报告转义序列，
						 * 而不是整个字符串。
						 */
						fc_lex->token_start = fc_s;
						FAIL_AT_CHAR_END(JSON_ESCAPING_INVALID);
				}
			}
			else if (strchr("\"\\/bfnrt", *fc_s) == NULL)
			{
				/*
				 * 如果我们不在乎去转义的话，处理会更简单
				 *
				 * 在这里很诱惑将 strchr() 调用去掉，改用 switch 语句，
				 * 但到目前为止的测试表明这并没有提升性能。
				 */
				fc_lex->token_start = fc_s;
				FAIL_AT_CHAR_END(JSON_ESCAPING_INVALID);
			}
		}
		else if (fc_lex->strval != NULL)
		{
			if (fc_hi_surrogate != -1)
				FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE);

			appendStringInfoChar(fc_lex->strval, *fc_s);
		}
	}

	if (fc_hi_surrogate != -1)
	{
		fc_lex->token_terminator = fc_s + 1;
		return JSON_UNICODE_LOW_SURROGATE;
	}

	/* 好极了，我们找到了字符串的结尾！ */
	fc_lex->prev_token_terminator = fc_lex->token_terminator;
	fc_lex->token_terminator = fc_s + 1;
	return JSON_SUCCESS;

#undef FAIL_AT_CHAR_START
#undef FAIL_AT_CHAR_END
}

/*
 * 输入流中的下一个标记被确定为数字；进行词法分析。
 *
 * 在 JSON 中，一个数字由四部分组成：
 *
 * (1) 一个可选的负号 ('-')。
 *
 * (2) 要么是单个 '0'，要么是一个或多个数字组成的字符串，且不以
 *	   '0' 开头。
 *
 * (3) 一个可选的小数部分，由一个句点 ('.') 后跟一个或多个数字组成。
 *	   （注意：虽然这部分可以完全省略，但不可以仅有小数点而后面没有
 *	   任何数字。）
 *
 * (4) 一个可选的指数部分，由 'e' 或 'E' 组成，后面可选地跟着 '+' 或 '-',
 *	   然后是一个或多个数字。（注意：如同小数部分，如果出现 'e' 或 'E'，
 *	   它必须后跟至少一个数字。）
 *
 * 传递给该函数的 's' 参数指向部分 2 的表面开始 - 即在任何可选的负号
 * 后的字符，或者如果没有负号，则是字符串的第一个字符。
 *
 * 如果 num_err 不为 NULL，我们将错误标志返回给 *num_err，而不是因格式不良的数字抛出错误。
 * 此外，如果 total_len 不为 NULL，则从 lex->input 到 token 结束+1 的距离
 * 将返回给 *total_len。
 */
static inline JsonParseErrorType fc_json_lex_number(JsonLexContext *fc_lex, char *fc_s,
				bool *fc_num_err, int *fc_total_len)
{
	bool		fc_error = false;
	int			fc_len = fc_s - fc_lex->input;

	/* 部分 (1)：前导符号指示。 */
	/* 调用者已经为我们做了这一点；所以不做任何操作。 */

	/* 部分 (2)：解析主数字字符串。 */
	if (fc_len < fc_lex->input_length && *fc_s == '0')
	{
		fc_s++;
		fc_len++;
	}
	else if (fc_len < fc_lex->input_length && *fc_s >= '1' && *fc_s <= '9')
	{
		do
		{
			fc_s++;
			fc_len++;
		} while (fc_len < fc_lex->input_length && *fc_s >= '0' && *fc_s <= '9');
	}
	else
		fc_error = true;

	/* 部分 (3)：解析可选的小数部分。 */
	if (fc_len < fc_lex->input_length && *fc_s == '.')
	{
		fc_s++;
		fc_len++;
		if (fc_len == fc_lex->input_length || *fc_s < '0' || *fc_s > '9')
			fc_error = true;
		else
		{
			do
			{
				fc_s++;
				fc_len++;
			} while (fc_len < fc_lex->input_length && *fc_s >= '0' && *fc_s <= '9');
		}
	}

	/* 部分 (4)：解析可选的指数。 */
	if (fc_len < fc_lex->input_length && (*fc_s == 'e' || *fc_s == 'E'))
	{
		fc_s++;
		fc_len++;
		if (fc_len < fc_lex->input_length && (*fc_s == '+' || *fc_s == '-'))
		{
			fc_s++;
			fc_len++;
		}
		if (fc_len == fc_lex->input_length || *fc_s < '0' || *fc_s > '9')
			fc_error = true;
		else
		{
			do
			{
				fc_s++;
				fc_len++;
			} while (fc_len < fc_lex->input_length && *fc_s >= '0' && *fc_s <= '9');
		}
	}

	/*
	 * 检查尾随的垃圾。与 json_lex() 一样，
	 * 这里的任何字母数字内容都应视为标记的一部分，以便进行错误报告。
	 */
	for (; fc_len < fc_lex->input_length && JSON_ALPHANUMERIC_CHAR(*fc_s); fc_s++, fc_len++)
		fc_error = true;

	if (fc_total_len != NULL)
		*fc_total_len = fc_len;

	if (fc_num_err != NULL)
	{
		/* 让调用者处理任何错误 */
		*fc_num_err = fc_error;
	}
	else
	{
		/* 返回标记的结束点 */
		fc_lex->prev_token_terminator = fc_lex->token_terminator;
		fc_lex->token_terminator = fc_s;
		/* 如果有错误，处理错误 */
		if (fc_error)
			return JSON_INVALID_TOKEN;
	}

	return JSON_SUCCESS;
}

/*
 * 报告解析错误。
 *
 * lex->token_start 和 lex->token_terminator 必须标识当前令牌。
 */
static JsonParseErrorType fc_report_parse_error(JsonParseContext fc_ctx, JsonLexContext *fc_lex)
{
	/* 处理输入提前结束的情况。 */
	if (fc_lex->token_start == NULL || fc_lex->token_type == JSON_TOKEN_END)
		return JSON_EXPECTED_MORE;

	/* 否则根据解析上下文选择错误类型。 */
	switch (fc_ctx)
	{
		case JSON_PARSE_END:
			return JSON_EXPECTED_END;
		case JSON_PARSE_VALUE:
			return JSON_EXPECTED_JSON;
		case JSON_PARSE_STRING:
			return JSON_EXPECTED_STRING;
		case JSON_PARSE_ARRAY_START:
			return JSON_EXPECTED_ARRAY_FIRST;
		case JSON_PARSE_ARRAY_NEXT:
			return JSON_EXPECTED_ARRAY_NEXT;
		case JSON_PARSE_OBJECT_START:
			return JSON_EXPECTED_OBJECT_FIRST;
		case JSON_PARSE_OBJECT_LABEL:
			return JSON_EXPECTED_COLON;
		case JSON_PARSE_OBJECT_NEXT:
			return JSON_EXPECTED_OBJECT_NEXT;
		case JSON_PARSE_OBJECT_COMMA:
			return JSON_EXPECTED_STRING;
	}

	/*
	 * 我们不使用 default: 情况，以便编译器会警告
	 * 未处理的枚举值。
	 */
	Assert(false);
	return JSON_SUCCESS;		/* 消除愚蠢编译器的警告 */
}


#ifndef FRONTEND
/*
 * 从词法上下文中提取当前令牌，用于错误报告。
 */
static char * fc_extract_token(JsonLexContext *fc_lex)
{
	int			fc_toklen = fc_lex->token_terminator - fc_lex->token_start;
	char	   *fc_token = palloc(fc_toklen + 1);

	memcpy(fc_token, fc_lex->token_start, fc_toklen);
	fc_token[fc_toklen] = '\0';
	return fc_token;
}

/*
 * 为 JSON 错误构造一个（已翻译的）详细信息消息。
 *
 * 请注意，由此例程生成的错误消息可能没有进行
 * palloc 分配，使其对前端代码不安全，因为没有办法
 * 知道这是否可以安全地 pfree。
 */
char * json_errdetail(JsonParseErrorType fc_error, JsonLexContext *fc_lex)
{
	switch (fc_error)
	{
		case JSON_SUCCESS:
			/* fall through to the fc_error code after switch */
			break;
		case JSON_ESCAPING_INVALID:
			return psprintf(_("Escape sequence \"\\%s\" is invalid."),
							fc_extract_token(fc_lex));
		case JSON_ESCAPING_REQUIRED:
			return psprintf(_("Character with value 0x%02x must be escaped."),
							(unsigned char) *(fc_lex->token_terminator));
		case JSON_EXPECTED_END:
			return psprintf(_("Expected end of input, but found \"%s\"."),
							fc_extract_token(fc_lex));
		case JSON_EXPECTED_ARRAY_FIRST:
			return psprintf(_("Expected array element or \"]\", but found \"%s\"."),
							fc_extract_token(fc_lex));
		case JSON_EXPECTED_ARRAY_NEXT:
			return psprintf(_("Expected \",\" or \"]\", but found \"%s\"."),
							fc_extract_token(fc_lex));
		case JSON_EXPECTED_COLON:
			return psprintf(_("Expected \":\", but found \"%s\"."),
							fc_extract_token(fc_lex));
		case JSON_EXPECTED_JSON:
			return psprintf(_("Expected JSON value, but found \"%s\"."),
							fc_extract_token(fc_lex));
		case JSON_EXPECTED_MORE:
			return _("The input string ended unexpectedly.");
		case JSON_EXPECTED_OBJECT_FIRST:
			return psprintf(_("Expected string or \"}\", but found \"%s\"."),
							fc_extract_token(fc_lex));
		case JSON_EXPECTED_OBJECT_NEXT:
			return psprintf(_("Expected \",\" or \"}\", but found \"%s\"."),
							fc_extract_token(fc_lex));
		case JSON_EXPECTED_STRING:
			return psprintf(_("Expected string, but found \"%s\"."),
							fc_extract_token(fc_lex));
		case JSON_INVALID_TOKEN:
			return psprintf(_("Token \"%s\" is invalid."),
							fc_extract_token(fc_lex));
		case JSON_UNICODE_CODE_POINT_ZERO:
			return _("\\u0000 cannot be converted to text.");
		case JSON_UNICODE_ESCAPE_FORMAT:
			return _("\"\\u\" must be followed by four hexadecimal digits.");
		case JSON_UNICODE_HIGH_ESCAPE:
			/* 注意：此情况仅在前端可达而非后端 */
			return _("Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8.");
		case JSON_UNICODE_HIGH_SURROGATE:
			return _("Unicode high surrogate must not follow a high surrogate.");
		case JSON_UNICODE_LOW_SURROGATE:
			return _("Unicode low surrogate must follow a high surrogate.");
	}

	/*
	 * 我们不使用 default: 情况，以便编译器会警告
	 * 未处理的枚举值。但不管怎样，这需要在这里，以覆盖
	 * 输入不正确的可能性。
	 */
	elog(ERROR, "unexpected json parse fc_error type: %d", (int) fc_error);
	return NULL;
}
#endif
